#include "Votante.h"
#include "Utils.h"
#include <sstream>
using namespace Entidades;

Votante::Votante() {
	this->elecciones = new vector<Eleccion*>;
	this->distrito = new Distrito();
}

string Votante::getNombreYApellido() const {
	return apeNom;
}

Distrito *Votante::getDistrito() const {
	return distrito;
}

int Votante::getDNI() const {
	return dni;
}

int Votante::getClave() const {
	return clave;
}

string Votante::getDomicilio() const {
	return domicilio;
}

vector<Eleccion*> *Votante::getElecciones() const {
	return elecciones;
}

void Votante::setNombreYApellido(string apeNom) {
	this->apeNom = apeNom;
}

void Votante::setDistrito(string nombreDelDistrito) {
	this->distrito->setNombre(nombreDelDistrito);
}

void Votante::setDNI(int dni) {
	this->dni = dni;
}

void Votante::setClave(int clave) {
	this->clave = clave;
}

void Votante::setDomicilio(string domicilio) {
	this->domicilio = domicilio;
}

void Votante::addEleccion(Eleccion *eleccion) {

	this->elecciones->push_back(eleccion);
}

bool Votante::validarContrasenia(string clave){

	return (this->clave == atoi(clave.c_str()));

}

void Votante::hidratarse(char* buffer, unsigned int tamanioDelBuffer) {

	//escribo el buffer en el stringStream
	stringstream* ss = new stringstream(stringstream::in | stringstream::out | stringstream::binary);
	ss->seekg(0, ios::beg);
	ss->write(buffer, tamanioDelBuffer);

	//int DNI
	ss->read((char*) &(this->dni), sizeof(int));

	//string apeNom
	this->apeNom = Utils::ObtenerSiguienteStringVariable(ss);

	//int clave
	ss->read((char*) &(this->clave), sizeof(int));

	//string domicilio
	this->domicilio += Utils::ObtenerSiguienteStringVariable(ss);

	//Distrito* distrito (clave: string nombre)
	this->distrito->setNombre(Utils::ObtenerSiguienteStringVariable(ss));

	//vector<Eleccion*>* elecciones (cantElecciones + clave - int fecha, string cargo -)
	unsigned int cantidadDeElecciones = 0;
	ss->read((char*) &(cantidadDeElecciones), sizeof(int));

	int *fecha = new int();
	for (unsigned int i = 0; i < cantidadDeElecciones; i++) {
		Eleccion* eleccion = new Eleccion();
		ss->read((char*) (fecha), sizeof(int));
		eleccion->setFecha(*fecha);
		eleccion->setCargo(Utils::ObtenerSiguienteStringVariable(ss));
		this->elecciones->push_back(eleccion);
	}
	delete fecha;

	delete ss;
}

char* Votante::construirBuffer() {

	//agrupo los atributos
	stringstream* ss = new stringstream(stringstream::in | stringstream::out | stringstream::binary);
	ss->seekp(0, ios::end);

	//DNI
	ss->write((char*) &(this->dni), sizeof(int));

	//NombreyApellido
	unsigned int tamanioDelNombre = apeNom.size();
	ss->write((char*) &tamanioDelNombre, sizeof(int));
	ss->write(apeNom.c_str(), tamanioDelNombre);

	//Clave
	ss->write((char*) &(this->clave), sizeof(int));

	//domicilio
	unsigned int tamanioDelDomicilio = domicilio.size();
	ss->write((char*) &tamanioDelDomicilio, sizeof(int));
	ss->write(domicilio.c_str(), tamanioDelDomicilio);

	//distrito (nombre)
	unsigned int tamanioDeLaClaveDeDistrito = distrito->getNombre().size();
	ss->write((char*) &tamanioDeLaClaveDeDistrito, sizeof(int));
	ss->write(distrito->getNombre().c_str(), tamanioDeLaClaveDeDistrito);

	//elecciones (cantidad de elecciones + fecha int y cargo string)
	unsigned int cantidadDeElecciones;
	cantidadDeElecciones = elecciones->size();
	ss->write((char*) &cantidadDeElecciones, sizeof(int));
	int* fecha = new int();
	int* tamanioCargo = new int();
	string* cargo = new string();
	for (unsigned int i = 0; i < cantidadDeElecciones; i++) {
		*fecha = elecciones->at(i)->getFecha();
		*tamanioCargo = elecciones->at(i)->getCargo()->getNombre().size();
		ss->write((char*) fecha, sizeof(int));
		ss->write((char*) tamanioCargo, sizeof(int));
		ss->write(elecciones->at(i)->getCargo()->getNombre().c_str(), *tamanioCargo);
	}
	delete fecha;
	delete cargo;
	delete tamanioCargo;

	//construyo el buffer
	unsigned int tamanioDelBuffer = this->getTamanioDelBuffer();
	char* buffer = new char[tamanioDelBuffer];
	ss->read(buffer, tamanioDelBuffer);
	delete ss;

	//lo devuelvo
	return buffer;
}

unsigned int Votante::getTamanioDelBuffer() {
	int tamanioDelBuffer = 6 * sizeof(int);
	tamanioDelBuffer += apeNom.size() + domicilio.size() + distrito->getNombre().size();

	for (unsigned int i = 0; i < elecciones->size(); i++) {
		tamanioDelBuffer += 2 * sizeof(int); // fecha + tamanioCargo
		tamanioDelBuffer += elecciones->at(i)->getCargo()->getNombre().size();
	}

	return tamanioDelBuffer;
}

void Votante::marcarComoBorrado() {

}

Votante::~Votante() {

	for(unsigned int i = 0; i < elecciones->size(); i++){
		delete this->elecciones->at(i);
	}

	delete this->elecciones;
	delete this->distrito;
}

